<?php

namespace app\admin\controller;

use app\common\controller\Backend;
use think\Db;
use Exception;
use think\exception\DbException;
use think\exception\PDOException;
use think\exception\ValidateException;
use app\admin\model\ProjectItems;
use app\admin\model\ProjectRencaiji;
use app\admin\model\ProjectAssess;

/**
 * 项目管理
 *
 * @icon fa fa-circle-o
 */
class Project extends Backend
{

    /**
     * Project模型对象
     * @var \app\admin\model\Project
     */
    protected $model = null;

    protected $projectConfig = null;
    protected $searchFields = 'project_name,admin.nickname';
    protected $excelLimit = 1500;
    protected $tenderTypeMapping = ['招标_1', '投标'];
    protected $exportXmlTips = '请导入控制价或投标XML文件';
    protected $noNeedRight = ['import_preview'];

    public function _initialize()
    {
        parent::_initialize();
        $this->model = new \app\admin\model\Project;
        $config = DB::name('config')->where('group', 'caijiaku')->column('value', 'name');
        $config = array_map(function ($item) {
            return json_decode($item, true);
        }, $config);
        $this->projectConfig = $config;
        $this->view->assign('projectConfig', $this->projectConfig);
        $this->assignconfig('projectConfig', $config);
        $tenderTypeList = $this->model->getTenderTypeList();
        $this->view->assign('tenderTypeList', $tenderTypeList);
        $this->assignconfig('tenderTypeList', $tenderTypeList);
        $action = strtolower($this->request->action());
        if (in_array($action, ['index'])) {
            $this->dataLimit = false;
        } else {
            $this->dataLimit = 'auth';
        }
    }



    /**
     * 默认生成的控制器所继承的父类中有index/add/edit/del/multi五个基础方法、destroy/restore/recyclebin三个回收站方法
     * 因此在当前控制器中可不用编写增删改查的代码,除非需要自己控制这部分逻辑
     * 需要将application/admin/library/traits/Backend.php中对应的方法复制到当前控制器,然后进行修改
     */

     /**
     * 查看
     *
     * @return string|Json
     * @throws \think\Exception
     * @throws DbException
     */
    public function index()
    {
        //设置过滤方法
        $this->request->filter(['strip_tags', 'trim']);
        if (false === $this->request->isAjax()) {
            return $this->view->fetch();
        }
        //如果发送的来源是 Selectpage，则转发到 Selectpage
        if ($this->request->request('keyField')) {
            if ($this->request->request('datalimit')) $this->dataLimit = $this->request->request('datalimit');
            return $this->selectpage();
        }
        [$where, $sort, $order, $offset, $limit] = $this->buildparams();
        $wheres = [];
        //排除超管数据
        if(!$this->auth->isSuperAdmin()) {
            //排除超级管理员
            $groupWhere = [
                'caijiakuid' => CAIJIAKU_ID,
                'status' => 'normal',
                'rules' => '*',
            ];
            $groupIds = Db::name('auth_group')->where($groupWhere)->column('id');
            $adminIds = Db::name('auth_group_access')->where(['group_id' => ['in', $groupIds]])->column('uid');
            $wheres['admin_id'] = ['not in', $adminIds];
        }
        $list = $this->model
            ->with(['admin'])
            ->where($where)
            ->where($wheres)
            ->order($sort, $order)
            ->paginate($limit);
            foreach ($list as $row) {
                $row->visible(['id','admin_id','project_name','project_address','pricing_date','project_class','project_bulid_cost','project_scale','square_build_cost','build_unit','construction_unit','structure_type','build_cost_type','build_form','taxation_type','contract_no','contract_name','createtime', 'admin.nickname', 'updatetime', 'tender_type']);
            }
        $result = ['total' => $list->total(), 'rows' => $list->items()];
        return json($result);
    }

    public function detail($ids = null)
    {
        $row = $this->model->where(['project.id' => $ids])->with([
            'admin',
        ])->find();
        if (!$row) {
            $this->error(__('No Results were found'));
        }
        $projectFiles = $row['project_files'] ? explode(',', $row['project_files']) : [];
        $row['project_files_arr'] = array_map(function ($item) {
            return cdnurl($item);
        }, $projectFiles);
        $contractFiles = $row['contract_files'] ? explode(',', $row['contract_files']) : [];
        $row['contract_files_arr'] = array_map(function ($item) {
            return cdnurl($item);
        }, $contractFiles);
        $preparedFiles = $row['prepared_files'] ? explode(',', $row['prepared_files']) : [];
        $row['prepared_files_arr'] = array_map(function ($item) {
            return cdnurl($item);
        }, $preparedFiles);
        $this->view->assign('row', $row);
        $this->view->assign('ids', $ids);
        $this->assignconfig("idinfo", ['id' => $ids,'project_name'=>$row['project_name']]);
        //获取明细数量
        $itemcount = (new ProjectItems())->where('project_id', $ids)->count();
        $rencaijicount = (new ProjectRencaiji())->where('project_id', $ids)->count();
        $assesscount = (new ProjectAssess())->where('project_id', $ids)->count();
        $infocount = [
            1 => $itemcount,
            2 => $rencaijicount,
            3 => $assesscount,
        ];
        $this->view->assign('infocount', $infocount);
        return $this->view->fetch();
    }

    /**
     * 添加
     *
     * @return string
     * @throws \think\Exception
     */
    public function add()
    {
        if (false === $this->request->isPost()) {
           
            return $this->view->fetch();
        }
        $params = $this->request->post('row/a');
        if (empty($params)) {
            $this->error(__('Parameter %s can not be empty', ''));
        }
        $params = $this->preExcludeFields($params);

        if ($this->dataLimit && $this->dataLimitFieldAutoFill) {
            $params[$this->dataLimitField] = $this->auth->id;
        }
        //判断项目是否已存在
        $projectInfo = $this->model->where(['project_name' => $params['project_name'], 'tender_type' => $params['tender_type']])->find();
        if (!empty($projectInfo)) {
            if (!empty($params['area_id']) && $projectInfo['area_id'] == $params['area_id']) {
                $this->error('['.$params['project_name'].']项目已存在');
            }
        }
        if (!empty($params['area_id'])) {
            $areaInfo = Db::name('area')->where('id', $params['area_id'])->find();
            $params['project_address'] = !empty($areaInfo['mergename']) ? str_replace('中国,', '', $areaInfo['mergename']) : '';
        }
        if (!empty($params['project_bulid_cost']) && !empty($params['project_scale']) && $params['project_scale'] > 0) {
            $params['square_build_cost'] = round($params['project_bulid_cost'] / $params['project_scale'], 2);
        }
        $result = false;
        Db::startTrans();
        try {
            //是否采用模型验证
            if ($this->modelValidate) {
                $name = str_replace("\\model\\", "\\validate\\", get_class($this->model));
                $validate = is_bool($this->modelValidate) ? ($this->modelSceneValidate ? $name . '.add' : $name) : $this->modelValidate;
                $this->model->validateFailException()->validate($validate);
            }
            $result = $this->model->allowField(true)->save($params);
            Db::commit();
        } catch (ValidateException|PDOException|Exception $e) {
            Db::rollback();
            $this->error($e->getMessage());
        }
        if ($result === false) {
            $this->error(__('No rows were inserted'));
        }
        $this->success();
    }

    /**
     * 编辑
     *
     * @param $ids
     * @return string
     * @throws DbException
     * @throws \think\Exception
     */
    public function edit($ids = null)
    {
        $row = $this->model->get($ids);
        if (!$row) {
            $this->error(__('No Results were found'));
        }
        $adminIds = $this->getDataLimitAdminIds();
        if (is_array($adminIds) && !in_array($row[$this->dataLimitField], $adminIds)) {
            $this->error(__('You have no permission'));
        }
        if (false === $this->request->isPost()) {
            $row['project_address_arr'] = explode(',', $row['project_address']);
            $this->view->assign('row', $row);
            return $this->view->fetch();
        }
        $params = $this->request->post('row/a');
        if (empty($params)) {
            $this->error(__('Parameter %s can not be empty', ''));
        }
        $params = $this->preExcludeFields($params);
        //判断项目是否已存在
        $projectInfo = $this->model->where(['project_name' => $params['project_name'], 'tender_type' => $params['tender_type']])->where('id', '<>', $ids)->find();
        if (!empty($projectInfo)) {
            if (!empty($params['area_id']) && $projectInfo['area_id'] == $params['area_id']) {
                $this->error('['.$params['project_name'].']项目已存在');
            }
        }
        if (!empty($params['area_id'])) {
            $areaInfo = Db::name('area')->where('id', $params['area_id'])->find();
            $params['project_address'] = !empty($areaInfo['mergename']) ? str_replace('中国,', '', $areaInfo['mergename']) : '';
        }
        if (!empty($params['project_bulid_cost']) && !empty($params['project_scale']) && $params['project_scale'] > 0) {
            $params['square_build_cost'] = round($params['project_bulid_cost'] / $params['project_scale'], 2);
        }
        $result = false;
        Db::startTrans();
        try {
            //是否采用模型验证
            if ($this->modelValidate) {
                $name = str_replace("\\model\\", "\\validate\\", get_class($this->model));
                $validate = is_bool($this->modelValidate) ? ($this->modelSceneValidate ? $name . '.edit' : $name) : $this->modelValidate;
                $row->validateFailException()->validate($validate);
            }
            $result = $row->allowField(true)->save($params);
            Db::commit();
        } catch (ValidateException|PDOException|Exception $e) {
            Db::rollback();
            $this->error($e->getMessage());
        }
        if (false === $result) {
            $this->error(__('No rows were updated'));
        }
        $this->success();
    }

    public function import()
    {
        if ($this->request->isPost() == false) {
            // $this->view->assign('project_info', []);
            $this->view->assign('tips', $this->exportXmlTips);
            return $this->view->fetch();
        }
        set_time_limit(0);
        $file = $this->request->request('file', '');
        $row = $this->request->request('row/a', []);
        if (empty($file)) {
            $this->error(__('Parameter %s can not be empty', 'file'));
        }
        
        $filePath = ROOT_PATH . DS .'public'. $file;
        if (!is_file($filePath)) {
            $this->error(__('No results were found'));
        }
        if (!file_exists($filePath)) {
            $this->error('文件不存在');
        }

        $ext = pathinfo($filePath, PATHINFO_EXTENSION);
        if (!in_array($ext, ['xml'])) {
            $this->error(__('Unknown data format'));
        }
        Db::startTrans();
        try{
            $xmlContent = file_get_contents($filePath);
            $xml = simplexml_load_string($xmlContent);
            $tender_type_txt = (string)$xml->文件类型;
            if (!in_array($tender_type_txt, $this->tenderTypeMapping)) {
                $this->error($this->exportXmlTips);
            }
            $tender_type = strpos($tender_type_txt,'投标') === false ? 1 : 2;
            $taxation_type_txt = (string)$xml['计税方式'];
            $taxation_type = array_flip($this->projectConfig['taxation_type'])[$taxation_type_txt] ?? 0;
            $pricing_method_txt = (string)$xml['报价方式'];
            $pricingMethodMapping = array_filter($this->projectConfig['pricing_method'], function($item) use ($pricing_method_txt) {
                return strpos($item, $pricing_method_txt) !== false || strpos($pricing_method_txt, $item) !== false;
            });
            $pricing_method = !empty($pricingMethodMapping) ? array_keys($pricingMethodMapping)[0] : 0;
            $pricing_inventory_txt = (string)$xml['清单规范'];
            $inventory_mapping = [
                '08规范' => '国标08清单',
                '13规范' => '国标13清单',
            ];
            $pricing_inventory_txt = $inventory_mapping[$pricing_inventory_txt] ?? '';
            $pricing_inventory = array_flip($this->projectConfig['pricing_inventory'])[$pricing_inventory_txt] ?? 0;
            $contracting_type_txt = (string)$xml['发包方式'];
            $contracting_type = array_flip($this->projectConfig['contracting_type'])[$contracting_type_txt] ?? 0;
            if (empty($row['structure_type'])) {
                $structure_type_txt = (string)$xml->工程描述->工程招标信息['工程结构'] ?? '';
                $structureTypeMapping = [];
                if (!empty($structure_type_txt)) {
                    $structureTypeMapping = array_filter($this->projectConfig['structure_type'], function($item) use ($structure_type_txt) {
                        return strpos($item, $structure_type_txt) !== false || strpos($structure_type_txt, $item) !== false;
                    });
                }
                //获取structureTypeMapping第一个key
                $structure_type = !empty($structureTypeMapping) ? array_keys($structureTypeMapping)[0] : 0;
            } else {
                $structure_type = $row['structure_type'];
            }
            //地址
            $project_address = (string)$xml->工程描述->工程招标信息['工程地点'] ?? '';
            $province_id = $row['province_id'] ?? 0;
            $city_id = $row['city_id'] ?? 0;
            $area_id = $row['area_id'] ?? 0;
            if (!empty($area_id)) {
                $areaInfo = Db::name('area')->where('id', $area_id)->find();
                if (!empty($areaInfo)) {
                    $project_address = !empty($areaInfo['mergename']) ? str_replace('中国,', '', $areaInfo['mergename']) : '';
                }
            } else if (!empty($city_id)) {
                $areaInfo = Db::name('area')->where('id', $city_id)->find();
                if (!empty($areaInfo)) {
                    $project_address = !empty($areaInfo['mergename']) ? str_replace('中国,', '', $areaInfo['mergename']) : '';
                }
            }
            // $pricing_date = $row['pricing_date'] ?? (string)$xml->工程描述->工程投标信息['编制时间'] ?? (string)$xml->工程描述->工程招标信息['编制时间'];
            $toub_date = (string)$xml->工程描述->工程投标信息['编制时间'] ?? '';
            $zhaob_date = (string)$xml->工程描述->工程招标信息['编制时间'] ?? '';
            $pricing_date = !empty($row['pricing_date']) ? $row['pricing_date'] : (!empty($toub_date) ? $toub_date : ($zhaob_date ? $zhaob_date : null));
            //判断pricing_date是否日期格式，不是则为null
            if (!preg_match('/^\d{4}-\d{2}-\d{2}$/', $pricing_date)) {
                $pricing_date = null;
            }
            $project_bulid_cost = $row['project_bulid_cost'] ?? (float)$xml->工程描述->工程投标信息->投标总价 ?? (float)$xml->工程描述->工程招标信息['控制价'] ?? 0;
            $project_scale = $row['project_scale'] ?? (float)$xml->工程描述->基本信息['建筑面积'] ?? '';
            $build_unit = $row['build_unit'] ?? (string)$xml->工程描述->工程招标信息['招标单位名称'] ?? (string)$xml->工程描述->工程投标信息['招标人'] ?? '';
            $build_form = $row['build_form'] ?? 0;
            $project_data = [
                'project_name' => (string)$xml->工程描述->基本信息['项目名称'],
                'province_id' => $province_id,
                'city_id' => $city_id,
                'area_id' => $area_id,
                'project_address' => $project_address,
                'tender_type' => $tender_type,
                'project_scale' => $project_scale,
                'project_bulid_cost' => $project_bulid_cost,
                'prepared_date' => (string)$xml->工程描述->工程投标信息['编制时间'] ?? (string)$xml->工程描述->工程招标信息['编制时间'],
                'pricing_date' => $pricing_date,
                'taxation_type' => $taxation_type,      
                'pricing_method' => $pricing_method,   
                'pricing_inventory' => $pricing_inventory,   
                'pricing_software' => (string)$xml['计价软件名称'] ?? '',   
                'contracting_type' => $contracting_type,   
                'structure_type' => $structure_type,   
                'build_unit' => $build_unit,   
                'prepared_by' => (string)$xml->工程描述->工程招标信息['编制人'] ?? '',   
                'admin_id' => $this->auth->id,
                'build_form' => $build_form,
                'xml_file' => $file,
                
                'createtime' => time(),
                'updatetime' => time(),
            ];
            //判断项目是否已存在
            $projectInfo = $this->model->where(['project_name' => $project_data['project_name'], 'tender_type' => $project_data['tender_type']])->find();
            if (!empty($projectInfo)) {
                throw new Exception('['.$project_data['project_name'].']项目已存在');
            }
            $project_res = $this->model->allowField(true)->save($project_data);
            if (!$project_res) {
                throw new Exception('项目创建失败');
            }
            $project_id = $this->model->id;
            // 提取分部分项工程量清单
            $rencaiji_codes = [];//记录所有已存取的编码
            foreach ($xml->总工程->单项工程 as $item) {
                $row = [
                    'caijiakuid' => CAIJIAKU_ID,
                    'admin_id' => $this->auth->id,
                    'project_id' => $project_id,
                    'name' => (string)$item['名称'],
                    'total_price' => (float)$item['金额'],
                    'appraise_price' => (float)$item['其中暂估价'],
                    'regulatory_fee' => (float)$item['规费'],
                    'level' => 1,
                    'createtime' => time(),
                    'updatetime' => time(),
                ];
                $firstId = Db::name('project_items')->insertGetId($row);
                if (!$firstId) {
                    throw new Exception(__('导入失败，请检查数据格式'));
                }
                foreach ($item->单位工程 as $unitpro) {
                    $major_txt = (string)$unitpro['定额专业'];
                    $major = array_flip($this->projectConfig['project_major'])[$major_txt] ?? 0;
                    $place_txt = (string)$unitpro['工程所在地'];
                    $project_place = array_flip($this->projectConfig['project_place'])[$place_txt] ?? 0;
                    $row = [
                        'caijiakuid' => CAIJIAKU_ID,
                        'admin_id' => $this->auth->id,
                        'project_id' => $project_id,
                        'name' => (string)$unitpro['名称'],
                        'code' => '',
                        'total_price' => (float)$unitpro['金额'],
                        'appraise_price' => (float)$unitpro['其中暂估价'],
                        'major' => $major,
                        'project_place' => $project_place,
                        'level' => 2,
                        'pid' => $firstId,
                        'path' => $firstId,
                        'createtime' => time(),
                        'updatetime' => time(),
                    ];
                    $twoId = Db::name('project_items')->insertGetId($row);
                    if (!$twoId) {
                        throw new Exception(__('导入失败，请检查数据格式'));
                    }
                    if (empty($unitpro->分部分项工程量清单->清单子目)) {
                        continue;
                    }
                    //分部分项工程量清单
                    foreach ($unitpro->分部分项工程量清单->清单子目 as $subItem) {
                        $row = [
                            'caijiakuid' => CAIJIAKU_ID,
                            'admin_id' => $this->auth->id,
                            'project_id' => $project_id,
                            'name' => (string)$subItem->项目名称,
                            'code' => (string)$subItem->项目编码,
                            'description' => (string)$subItem->项目特征,
                            'quantity' => (float)$subItem->工程数量,
                            'unit' => (string)$subItem->计量单位,
                            'unit_price' => (float)$subItem->综合单价,
                            'total_price' => (float)$subItem->综合合价,
                            'labor_cost' => (float)$subItem->综合单价['人工费单价'],
                            'material_cost' => (float)$subItem->综合单价['材料费单价'],
                            'machinery_cost' => (float)$subItem->综合单价['机械使用费单价'],
                            'management_cost' => (float)$subItem->综合单价['管理费单价'],
                            'profit' => (float)$subItem->综合单价['利润单价'],
                            'calculation_rules' => (string)$subItem->计算规则,
                            'appraise_price' => 0,
                            'level' => 3,
                            'pid' => $twoId,
                            'path' => $firstId.','.$twoId,
                            'createtime' => time(),
                            'updatetime' => time(),
                        ];
                        $threeId = Db::name('project_items')->insertGetId($row);
                        if (!$threeId) {
                            throw new Exception(__('导入失败，请检查数据格式'));
                        }
                        if (empty($subItem->清单明细->定额子目)) {
                            continue;
                        }
                        $subchildData = [];
                        foreach ($subItem->清单明细->定额子目 as $subchildItem) {
                            $major_txt = (string)$subchildItem->专业;
                            $major = array_flip($this->projectConfig['project_major'])[$major_txt] ?? 0;
                            $subchildData[] = [
                                'caijiakuid' => CAIJIAKU_ID,
                                'admin_id' => $this->auth->id,
                                'project_id' => $project_id,
                                'name' => (string)$subchildItem->名称,
                                'code' => (string)$subchildItem->编码,
                                'description' => (string)$subchildItem->项目特征,
                                'quantity' => (float)$subchildItem->数量,
                                'unit' => (string)$subchildItem->单位,
                                'unit_price' => (float)$subchildItem->综合单价,
                                'total_price' => (float)$subchildItem->综合合价,
                                'labor_cost' => (float)$subchildItem->综合单价['人工费单价'],
                                'material_cost' => (float)$subchildItem->综合单价['材料费单价'],
                                'machinery_cost' => (float)$subchildItem->综合单价['机械使用费单价'],
                                'management_cost' => (float)$subchildItem->综合单价['管理费单价'],
                                'profit' => (float)$subchildItem->综合单价['利润单价'],
                                'pricing_base' => (float)$subchildItem->计价基数,
                                'major' => $major,
                                'appraise_price' => 0,
                                'level' => 4,
                                'pid' => $threeId,
                                'path' => $firstId.','.$twoId.','.$threeId,
                                'createtime' => time(),
                                'updatetime' => time(),
                            ];
                            //人材机
                            if (empty($subchildItem->定额明细)) {
                                continue;
                            }
                            $recaiji = [];
                            foreach ($subchildItem->定额明细->工料机子目 as $recaijiItem) {
                                $code = (string)$recaijiItem['编码'];
                                $catename_key = (int)$recaijiItem['类别'];
                                $catename = $this->projectConfig['materials_types'][$catename_key] ?? '';
                                if (in_array($code, $rencaiji_codes)) continue;
                                $recaiji[] = [
                                    'caijiakuid' => CAIJIAKU_ID,
                                    'admin_id' => $this->auth->id,
                                    'project_id' => $project_id,
                                    'name' => (string)$recaijiItem['名称'],
                                    'code' => $code,
                                    'description' => (string)$recaijiItem['规格型号'],
                                    'unit' => (string)$recaijiItem['单位'],
                                    'quantity' => (float)$recaijiItem['数量'],
                                    'tax_unit_price' => (float)$recaijiItem['市场价'],
                                    'tax_total_price' => (float)$recaijiItem['合价'],
                                    'catename' => $catename,
                                    'createtime' => time(),
                                    'updatetime' => time(),
                                ];
                                $rencaiji_codes[] = $code;
                            }
                            if (!empty($recaiji)) {
                                $rs = Db::name('project_rencaiji')->insertAll($recaiji);
                                if (!$rs) {
                                    throw new Exception(__('导入失败，请检查数据格式'));
                                }
                            }

                        }
                        if (!empty($subchildData)) {
                           $rs = Db::name('project_items')->insertAll($subchildData);
                           if (!$rs) {
                                throw new Exception(__('导入失败，请检查数据格式'));
                            }
                        }
                    }
                    if (empty($unitpro->措施项目清单->措施子目)) {
                        continue;
                    }
                    //措施项目清单
                    foreach ($unitpro->措施项目清单->措施子目 as $subItem) {
                        $class = (string) $subItem->项目类型;
                        if ($class == '总价') {
                            continue;
                        }
                        $row = [
                            'caijiakuid' => CAIJIAKU_ID,
                            'admin_id' => $this->auth->id,
                            'project_id' => $project_id,
                            'name' => (string)$subItem->项目名称,
                            'code' => (string)$subItem->项目编码,
                            'description' => (string)$subItem->项目特征描述,
                            'quantity' => (float)$subItem->工程数量,
                            'unit' => (string)$subItem->计量单位,
                            'unit_price' => (float)$subItem->综合单价,
                            'total_price' => (float)$subItem->综合合价,
                            'labor_cost' => (float)$subItem->综合单价['人工费单价'],
                            'material_cost' => (float)$subItem->综合单价['材料费单价'],
                            'machinery_cost' => (float)$subItem->综合单价['机械使用费单价'],
                            'management_cost' => (float)$subItem->综合单价['管理费单价'],
                            'profit' => (float)$subItem->综合单价['利润单价'],
                            'calculation_rules' => (string)$subItem->计算规则,
                            'appraise_price' => 0,
                            'level' => 3,
                            'pid' => $twoId,
                            'path' => $firstId.','.$twoId,
                            'createtime' => time(),
                            'updatetime' => time(),
                        ];
                        $threeId = Db::name('project_items')->insertGetId($row);
                        if (!$threeId) {
                            throw new Exception(__('导入失败，请检查数据格式'));
                        }
                        if (empty($subItem->措施明细->定额子目)) {
                            continue;
                        }
                        $subchildData = [];
                        foreach ($subItem->措施明细->定额子目 as $subchildItem) {
                            $major_txt = (string)$subchildItem->专业;
                            $major = array_flip($this->projectConfig['project_major'])[$major_txt] ?? 0;
                            $subchildData[] = [
                                'caijiakuid' => CAIJIAKU_ID,
                                'admin_id' => $this->auth->id,
                                'project_id' => $project_id,
                                'name' => (string)$subchildItem->名称 ?? '',
                                'code' => (string)$subchildItem->编码 ?? '',
                                'description' => '',
                                'quantity' => (float)$subchildItem->数量,
                                'unit' => (string)$subchildItem->单位,
                                'unit_price' => (float)$subchildItem->综合单价,
                                'total_price' => (float)$subchildItem->综合合价,
                                'labor_cost' => (float)$subchildItem->综合单价['人工费单价'],
                                'material_cost' => (float)$subchildItem->综合单价['材料费单价'],
                                'machinery_cost' => (float)$subchildItem->综合单价['机械使用费单价'],
                                'management_cost' => (float)$subchildItem->综合单价['管理费单价'],
                                'profit' => (float)$subchildItem->综合单价['利润单价'],
                                'pricing_base' => (float)$subchildItem->计价基数,
                                'major' => $major,
                                'appraise_price' => 0,
                                'level' => 4,
                                'pid' => $threeId,
                                'path' => $firstId.','.$twoId.','.$threeId,
                                'createtime' => time(),
                                'updatetime' => time(),
                            ];
                            //人材机
                            if (empty($subchildItem->定额明细)) {
                                continue;
                            }
                            $recaiji = [];
                            foreach ($subchildItem->定额明细->工料机子目 as $recaijiItem) {
                                $code = (string)$recaijiItem['编码'];
                                if (in_array($code, $rencaiji_codes)) continue;
                                $catename_key = (int)$recaijiItem['类别'];
                                $catename = $this->projectConfig['materials_types'][$catename_key] ?? '';
                                $recaiji[] = [
                                    'caijiakuid' => CAIJIAKU_ID,
                                    'admin_id' => $this->auth->id,
                                    'project_id' => $project_id,
                                    'name' => (string)$recaijiItem['名称'],
                                    'code' => (string)$recaijiItem['编码'],
                                    'description' => (string)$recaijiItem['规格型号'],
                                    'unit' => (string)$recaijiItem['单位'],
                                    'quantity' => (float)$recaijiItem['数量'],
                                    'tax_unit_price' => (float)$recaijiItem['市场价'],
                                    'tax_total_price' => (float)$recaijiItem['合价'],
                                    'catename' => $catename,
                                    'createtime' => time(),
                                    'updatetime' => time(),
                                ];
                                $rencaiji_codes[] = $code;
                            }
                            if (!empty($recaiji)) {
                                $rs = Db::name('project_rencaiji')->insertAll($recaiji);
                                if (!$rs) {
                                    throw new Exception(__('导入失败，请检查数据格式'));
                                }
                            }
                        }
                        if (!empty($subchildData)) {
                            $rs = Db::name('project_items')->insertAll($subchildData);
                            if (!$rs) {
                                throw new Exception(__('导入失败，请检查数据格式'));
                            }
                        }
                    }
                }
            }
            $project_assess = [];
            if (!empty($xml->总工程->材料总汇->评审材料)) {
                foreach ($xml->总工程->材料总汇->评审材料->评审材料子目 as $value) {
                    $catename_key = (int)$value['类别'];
                    $catename = $this->projectConfig['materials_types'][$catename_key] ?? '';
                    $project_assess[] = [
                        'caijiakuid' => CAIJIAKU_ID,
                        'admin_id' => $this->auth->id,
                        'project_id' => $project_id,
                        'name' => (string)$value['名称'],
                        'code' => (string)$value['编码'],
                        'description' => (string)$value['规格型号'],
                        'unit' => (string)$value['单位'],
                        'quantity' => (float)$value['数量'],
                        'unit_price' => (float)$value['市场单价'],
                        'total_price' => (float)$value['合价'],
                        'reference_price' => (float)$value['评审参考价'],
                        'tax' => (float)$value['进项税率'],
                        'catename' => $catename,
                        'createtime' => time(),
                        'updatetime' => time(),
                    ];
                }
            }
            if (!empty($project_assess)) {
                $chunkSize = 200; // 每次插入的数据条数
                $dataChunks = array_chunk($project_assess, $chunkSize); // 将数据分割成小数组
                foreach ($dataChunks as $chunk) {
                    $res = Db::name('project_assess')->insertAll($chunk); // 分批插入数据
                }
            }
            Db::commit();
        } catch (\Exception $e) {
            Db::rollback();
            $this->error($e->getMessage());
        }
        $this->success('导入成功');

        
    }

    public function import_preview()
    {
        $file = $this->request->request('file');
        if (!$file) {
            $this->error(__('Parameter %s can not be empty', 'file'));
        }
        $filePath = ROOT_PATH . DS . 'public' . DS . $file;
        if (!is_file($filePath)) {
            $this->error(__('No results were found'));
        }
        //实例化reader
        $ext = pathinfo($filePath, PATHINFO_EXTENSION);
        if (!in_array($ext, ['xml'])) {
            $this->error(__('Unknown data format'));
        }
        $xmlContent = file_get_contents($filePath);
        $xml = simplexml_load_string($xmlContent);
        $tender_type_txt = (string)$xml->文件类型;
        if (!in_array($tender_type_txt, $this->tenderTypeMapping)) {
            $this->error($this->exportXmlTips);
        }
        $project_name = (string)$xml->工程描述->基本信息['项目名称'];
        //获取地区
        $province_id = $city_id = $area_id = 0;
        $province_name = $city_name = $area_name = '';
        $project_address = (string)$xml->工程描述->工程招标信息['工程地点'] ?? '';
        // 合并处理县/区逻辑
        foreach (['县', '区', '市'] as $keyword) {
            if (strpos($project_name, $keyword) !== false) {
                $area_txt = trim(explode($keyword, $project_name)[0]);
                $area = Db::name('area')
                    ->where('name|shortname', $area_txt)
                    ->find();
                
                if ($area) {
                    if ($area['level'] == 2) {
                        $city_id = $area['id'];
                        $province_id = $area['pid'];
                        $project_address = str_replace('中国,', '', $area['mergename']);
                        list($province_name, $city_name) = explode(',', $project_address);
                    } else if ($area['level'] == 3) {
                        $area_id = $area['id'];
                        $city_id = $area['pid'];
                        $project_address = str_replace('中国,', '', $area['mergename']);
                        $province_id = Db::name('area')->where('id', $city_id)->value('pid');
                        list($province_name, $city_name, $area_name) = explode(',', $project_address);
                    }
                    break;
                }
            }
        }
        $toub_date = (string)$xml->工程描述->工程投标信息['编制时间'] ?? '';
        $zhaob_date = (string)$xml->工程描述->工程招标信息['编制时间'] ?? '';
        $pricing_date = !empty($toub_date) ? $toub_date : ($zhaob_date ? $zhaob_date : null);
        //判断pricing_date是否日期格式，不是则为null
        if (!preg_match('/^\d{4}-\d{2}-\d{2}$/', $pricing_date)) {
            $pricing_date = null;
        }
        $project_data = [
            'project_name' => $project_name,
            'project_address' => $project_address,
            'tender_type' => (string)$xml->文件类型 ?? '',
            'project_scale' => (float)$xml->工程描述->基本信息['建筑面积'] ?? '',
            'project_bulid_cost' => (float)$xml->工程描述->工程投标信息->投标总价 ?? (float)$xml->工程描述->工程招标信息['控制价'] ?? 0,
            'prepared_date' => $pricing_date,
            'pricing_date' => $pricing_date,
            'taxation_type' => (string)$xml['计税方式'] ?? '',   
            'pricing_method' => (string)$xml['报价方式'] ?? '',   
            'pricing_inventory' => (string)$xml['清单规范'] ?? '',   
            'pricing_software' => (string)$xml['计价软件名称'] ?? '',   
            'contracting_type' => (string)$xml['发包方式'] ?? '',   
            'structure_type' => (string)$xml->工程描述->工程招标信息['工程结构'] ?? '',   
            'build_unit' => (string)$xml->工程描述->工程招标信息['招标单位名称'] ?? (string)$xml->工程描述->工程投标信息['招标人'] ?? '',   
            'prepared_by' => (string)$xml->工程描述->工程招标信息['编制人'] ?? '',   
            'build_form' => '',   
            'province_id' => $province_id,
            'city_id' => $city_id,
            'area_id' => $area_id,
            'province_name' => $province_name,
            'city_name' => $city_name,
            'area_name' => $area_name,
        ];

        // 提取分部分项工程量清单
        $project_items = [];
        $project_rencaiji = [];
        $rencaiji_codes = [];
        foreach ($xml->总工程->单项工程 as $item) {
            $project_items[] = [
                'name' => (string)$item['名称'],
                'code' => '',
                'total_price' => (float)$item['金额'],
                'appraise_price' => (float)$item['其中暂估价'],
                'regulatory_fee' => (float)$item['规费'],
                'level' => 1
            ];
            foreach ($item->单位工程 as $unitpro) {
                $project_items[] = [
                    'name' => (string)$unitpro['名称'],
                    'code' => '',
                    'total_price' => (float)$unitpro['金额'],
                    'appraise_price' => (float)$unitpro['其中暂估价'],
                    'major' => (float)$unitpro['定额专业'],
                    'level' => 2
                ];
                if (empty($unitpro->分部分项工程量清单->清单子目)) {
                    continue;
                }
                foreach ($unitpro->分部分项工程量清单->清单子目 as $subItem) {
                    $project_items[] = [
                        'name' => (string)$subItem->项目名称,
                        'code' => (string)$subItem->项目编码,
                        'description' => (string)$subItem->项目特征,
                        'quantity' => (float)$subItem->工程数量,
                        'unit' => (string)$subItem->计量单位,
                        'unit_price' => (float)$subItem->综合单价,
                        'total_price' => (float)$subItem->综合合价,
                        'appraise_price' => 0,
                        'calculation_rules' => (string)$subItem->计算规则,
                        'level' => 3
                    ];
                    if (empty($subItem->清单明细->定额子目)) {
                        continue;
                    }
                    foreach ($subItem->清单明细->定额子目 as $subchildItem) {
                        $project_items[] = [
                            'name' => (string)$subchildItem->名称,
                            'code' => (string)$subchildItem->编码,
                            'description' => (string)$subchildItem->项目特征,
                            'quantity' => (float)$subchildItem->数量,
                            'unit' => (string)$subchildItem->单位,
                            'unit_price' => (float)$subchildItem->综合单价,
                            'total_price' => (float)$subchildItem->综合合价,
                            'appraise_price' => 0,
                            'pricing_base' => (float)$subchildItem->计价基数,
                            'level' => 4
                        ];
                        //人材机
                        if (empty($subchildItem->定额明细)) {
                            continue;
                        }
                        foreach ($subchildItem->定额明细->工料机子目 as $recaijiItem) {
                            $code = (string)$recaijiItem['编码'];
                            if (in_array($code, $rencaiji_codes)) continue;
                            $project_rencaiji[] = [
                                'name' => (string)$recaijiItem['名称'],
                                'code' => (string)$recaijiItem['编码'],
                                'description' => (string)$recaijiItem['规格型号'],
                                'unit' => (string)$recaijiItem['单位'],
                                'quantity' => (float)$recaijiItem['数量'],
                                'tax_unit_price' => (float)$recaijiItem['市场价'],
                                'tax_total_price' => (float)$recaijiItem['合价'],
                            ];
                            $rencaiji_codes[] = $code;
                        }
                    }
                    
                }
                if (empty($unitpro->措施项目清单->措施子目)) {
                    continue;
                }
                //措施项目清单
                foreach ($unitpro->措施项目清单->措施子目 as $subItem) {
                    $project_items[] = [
                        'name' => (string)$subItem->项目名称,
                        'code' => (string)$subItem->项目编码,
                        'description' => (string)$subItem->项目特征描述,
                        'quantity' => (float)$subItem->工程数量,
                        'unit' => (string)$subItem->计量单位,
                        'unit_price' => (float)$subItem->综合单价,
                        'total_price' => (float)$subItem->综合合价,
                        'calculation_rules' => (string)$subItem->计算规则,
                        'appraise_price' => 0,
                        'level' => 3,
                        'createtime' => time(),
                        'updatetime' => time(),
                    ];
                    if (empty($subItem->措施明细->定额子目)) {
                        continue;
                    }
                    foreach ($subItem->措施明细->定额子目 as $subchildItem) {
                        $project_items[] = [
                            'name' => (string)$subchildItem->名称 ?? '',
                            'code' => (string)$subchildItem->编码 ?? '',
                            'description' => '',
                            'quantity' => (float)$subchildItem->数量,
                            'unit' => (string)$subchildItem->单位,
                            'unit_price' => (float)$subchildItem->综合单价,
                            'total_price' => (float)$subchildItem->综合合价,
                            'labor_cost' => (float)$subchildItem->综合单价['人工费单价'],
                            'material_cost' => (float)$subchildItem->综合单价['材料费单价'],
                            'machinery_cost' => (float)$subchildItem->综合单价['机械使用费单价'],
                            'management_cost' => (float)$subchildItem->综合单价['管理费单价'],
                            'profit' => (float)$subchildItem->综合单价['利润单价'],
                            'pricing_base' => (float)$subchildItem->计价基数,
                            'major' => (string)$subchildItem->专业,
                            'appraise_price' => 0,
                            'level' => 4,
                            'createtime' => time(),
                            'updatetime' => time(),
                        ];
                        //人材机
                        if (empty($subchildItem->定额明细)) {
                            continue;
                        }
                        foreach ($subchildItem->定额明细->工料机子目 as $recaijiItem) {
                            $code = (string)$recaijiItem['编码'];
                            if (in_array($code, $rencaiji_codes)) continue;
                            $project_rencaiji[] = [
                                'name' => (string)$recaijiItem['名称'],
                                'code' => (string)$recaijiItem['编码'],
                                'description' => (string)$recaijiItem['规格型号'],
                                'unit' => (string)$recaijiItem['单位'],
                                'quantity' => (float)$recaijiItem['数量'],
                                'tax_unit_price' => (float)$recaijiItem['市场价'],
                                'tax_total_price' => (float)$recaijiItem['合价'],
                                'createtime' => time(),
                                'updatetime' => time(),
                            ];
                            $rencaiji_codes[] = $code;
                        }
                    }
                }
            }
            
        }
        $project_assess = [];
        if (!empty($xml->总工程->材料总汇->评审材料)) {
            foreach ($xml->总工程->材料总汇->评审材料->评审材料子目 as $value) {
                $catename_key = (int)$value['类别'];
                $catename = $this->projectConfig['materials_types'][$catename_key] ?? '';
                $project_assess[] = [
                    'name' => (string)$value['名称'],
                    'code' => (string)$value['编码'],
                    'description' => (string)$value['规格型号'],
                    'unit' => (string)$value['单位'],
                    'quantity' => (float)$value['数量'],
                    'unit_price' => (float)$value['市场单价'],
                    'total_price' => (float)$value['合价'],
                    'reference_price' => (float)$value['评审参考价'],
                    'tax' => (float)$value['进项税率'],
                    'catename' => $catename,
                ];
            }
        }

        if(count($project_items)==0){
            $this->error(__('文档识别失败，文档数据为空'));
        }
        $return = [
            'project_data' => $project_data,
            'project_assess' => $project_assess,
            'project_rencaiji' => $project_rencaiji,
            'data' => $project_items,
        //     'count' => count($newrowdata),
            'limit' => $this->excelLimit,
            'batchtimes' => 1
        ];
        $this->success('导入成功', '', $return);
    }

    /**
     * 批量导入
     *
     *
     * @return void
     */
    public function batchimport()
    {
        if ($this->request->isPost() == false) {
            $this->view->assign('tips', $this->exportXmlTips);
            return $this->view->fetch();
        }
        set_time_limit(0);
        $files = $this->request->request('files', '');
        $currentIndex = $this->request->request('currentIndex', 0);
        $row = $this->request->request('row/a', []);
        if (empty($files)) {
            $this->error(__('Parameter %s can not be empty', 'files'));
        }
        $filesArr = explode(',', $files);
        $file = $filesArr[$currentIndex];
        if (empty($file)) {
            $this->error(__('Parameter %s can not be empty', 'files'));
        }
        
        $filePath = ROOT_PATH . DS .'public'. $file;
        if (!is_file($filePath)) {
            $this->error(__('No results were found'));
        }
        if (!file_exists($filePath)) {
            $this->error('文件不存在');
        }

        $ext = pathinfo($filePath, PATHINFO_EXTENSION);
        if (!in_array($ext, ['xml'])) {
            $this->error(__('Unknown data format'));
        }
        Db::startTrans();
        try{
            $xmlContent = file_get_contents($filePath);
            $xml = simplexml_load_string($xmlContent);
            $tender_type_txt = (string)$xml->文件类型;
            if (!in_array($tender_type_txt, $this->tenderTypeMapping)) {
                $this->error($this->exportXmlTips);
            }
            $tender_type = strpos($tender_type_txt,'投标') === false ? 1 : 2;
            $taxation_type_txt = (string)$xml['计税方式'];
            $taxation_type = array_flip($this->projectConfig['taxation_type'])[$taxation_type_txt] ?? 0;
            $pricing_method_txt = (string)$xml['报价方式'];
            $pricingMethodMapping = array_filter($this->projectConfig['pricing_method'], function($item) use ($pricing_method_txt) {
                return strpos($item, $pricing_method_txt) !== false || strpos($pricing_method_txt, $item) !== false;
            });
            $pricing_method = !empty($pricingMethodMapping) ? array_keys($pricingMethodMapping)[0] : 0;
            $pricing_inventory_txt = (string)$xml['清单规范'];
            $inventory_mapping = [
                '08规范' => '国标08清单',
                '13规范' => '国标13清单',
            ];
            $pricing_inventory_txt = $inventory_mapping[$pricing_inventory_txt] ?? '';
            $pricing_inventory = array_flip($this->projectConfig['pricing_inventory'])[$pricing_inventory_txt] ?? 0;
            $contracting_type_txt = (string)$xml['发包方式'];
            $contracting_type = array_flip($this->projectConfig['contracting_type'])[$contracting_type_txt] ?? 0;
            if (empty($row['structure_type'])) {
                $structure_type_txt = (string)$xml->工程描述->工程招标信息['工程结构'] ?? '';
                $structureTypeMapping = [];
                if (!empty($structure_type_txt)) {
                    $structureTypeMapping = array_filter($this->projectConfig['structure_type'], function($item) use ($structure_type_txt) {
                        return strpos($item, $structure_type_txt) !== false || strpos($structure_type_txt, $item) !== false;
                    });
                }
                //获取structureTypeMapping第一个key
                $structure_type = !empty($structureTypeMapping) ? array_keys($structureTypeMapping)[0] : 0;
            } else {
                $structure_type = $row['structure_type'];
            }
            //地址
            $project_address = (string)$xml->工程描述->工程招标信息['工程地点'] ?? '';
            $province_id = $row['province_id'] ?? 0;
            $city_id = $row['city_id'] ?? 0;
            $area_id = $row['area_id'] ?? 0;
            if (!empty($area_id)) {
                $areaInfo = Db::name('area')->where('id', $area_id)->find();
                if (!empty($areaInfo)) {
                    $project_address = !empty($areaInfo['mergename']) ? str_replace('中国,', '', $areaInfo['mergename']) : '';
                }
            } else if (!empty($city_id)) {
                $areaInfo = Db::name('area')->where('id', $city_id)->find();
                if (!empty($areaInfo)) {
                    $project_address = !empty($areaInfo['mergename']) ? str_replace('中国,', '', $areaInfo['mergename']) : '';
                }
            }
            $project_name = (string)$xml->工程描述->基本信息['项目名称'];
            //获取地区
            $province_id = $city_id = $area_id = 0;
            // $province_name = $city_name = $area_name = '';
            $project_address = (string)$xml->工程描述->工程招标信息['工程地点'] ?? '';
            // 合并处理县/区逻辑
            foreach (['县', '区', '市'] as $keyword) {
                if (strpos($project_name, $keyword) !== false) {
                    $area_txt = trim(explode($keyword, $project_name)[0]);
                    $area = Db::name('area')
                        ->where('name|shortname', $area_txt)
                        ->find();
                    
                    if ($area) {
                        if ($area['level'] == 2) {
                            $city_id = $area['id'];
                            $province_id = $area['pid'];
                            $project_address = str_replace('中国,', '', $area['mergename']);
                        } else if ($area['level'] == 3) {
                            $area_id = $area['id'];
                            $city_id = $area['pid'];
                            $project_address = str_replace('中国,', '', $area['mergename']);
                            $province_id = Db::name('area')->where('id', $city_id)->value('pid');
                        }
                        break;
                    }
                }
            }
            // $pricing_date = (string)$xml->工程描述->工程投标信息['编制时间'] ?? (string)$xml->工程描述->工程招标信息['编制时间'] ?? $row['pricing_date'];
            $toub_date = (string)$xml->工程描述->工程投标信息['编制时间'] ?? '';
            $zhaob_date = (string)$xml->工程描述->工程招标信息['编制时间'] ?? '';
            $pricing_date = !empty($toub_date) ? $toub_date : ($zhaob_date ? $zhaob_date : $row['pricing_date'] ?? null);
            //判断pricing_date是否日期格式，不是则为null
            if (!preg_match('/^\d{4}-\d{2}-\d{2}$/', $pricing_date)) {
                $pricing_date = null;
            }
            $project_bulid_cost = $row['project_bulid_cost'] ?? (float)$xml->工程描述->工程投标信息->投标总价 ?? (float)$xml->工程描述->工程招标信息['控制价'] ?? 0;
            $project_scale = $row['project_scale'] ?? (float)$xml->工程描述->基本信息['建筑面积'] ?? '';
            $build_unit = $row['build_unit'] ?? (string)$xml->工程描述->工程招标信息['招标单位名称'] ?? (string)$xml->工程描述->工程投标信息['招标人'] ?? '';
            $build_form = $row['build_form'] ?? 0;
            $project_data = [
                'project_name' => (string)$xml->工程描述->基本信息['项目名称'],
                'province_id' => $province_id,
                'city_id' => $city_id,
                'area_id' => $area_id,
                'project_address' => $project_address,
                'tender_type' => $tender_type,
                'project_scale' => $project_scale,
                'project_bulid_cost' => $project_bulid_cost,
                'prepared_date' => (string)$xml->工程描述->工程投标信息['编制时间'] ?? (string)$xml->工程描述->工程招标信息['编制时间'],
                'pricing_date' => $pricing_date,
                'taxation_type' => $taxation_type,      
                'pricing_method' => $pricing_method,   
                'pricing_inventory' => $pricing_inventory,   
                'pricing_software' => (string)$xml['计价软件名称'] ?? '',   
                'contracting_type' => $contracting_type,   
                'structure_type' => $structure_type,   
                'build_unit' => $build_unit,   
                'prepared_by' => (string)$xml->工程描述->工程招标信息['编制人'] ?? '',   
                'admin_id' => $this->auth->id,
                'build_form' => $build_form,
                'xml_file' => $file,
                
                'createtime' => time(),
                'updatetime' => time(),
            ];
            //判断项目是否已存在
            $projectInfo = $this->model->where(['project_name' => $project_data['project_name'], 'tender_type' => $project_data['tender_type']])->find();
            if (!empty($projectInfo)) {
                throw new Exception('['.$project_data['project_name'].']项目已存在');
            }
            $project_res = $this->model->allowField(true)->save($project_data);
            if (!$project_res) {
                throw new Exception('项目创建失败');
            }
            $project_id = $this->model->id;
            // 提取分部分项工程量清单
            $rencaiji_codes = [];//记录所有已存取的编码
            foreach ($xml->总工程->单项工程 as $item) {
                $row = [
                    'caijiakuid' => CAIJIAKU_ID,
                    'admin_id' => $this->auth->id,
                    'project_id' => $project_id,
                    'name' => (string)$item['名称'],
                    'total_price' => (float)$item['金额'],
                    'appraise_price' => (float)$item['其中暂估价'],
                    'regulatory_fee' => (float)$item['规费'],
                    'level' => 1,
                    'createtime' => time(),
                    'updatetime' => time(),
                ];
                $firstId = Db::name('project_items')->insertGetId($row);
                if (!$firstId) {
                    throw new Exception(__('导入失败，请检查数据格式'));
                }
                foreach ($item->单位工程 as $unitpro) {
                    $major_txt = (string)$unitpro['定额专业'];
                    $major = array_flip($this->projectConfig['project_major'])[$major_txt] ?? 0;
                    $place_txt = (string)$unitpro['工程所在地'];
                    $project_place = array_flip($this->projectConfig['project_place'])[$place_txt] ?? 0;
                    $row = [
                        'caijiakuid' => CAIJIAKU_ID,
                        'admin_id' => $this->auth->id,
                        'project_id' => $project_id,
                        'name' => (string)$unitpro['名称'],
                        'code' => '',
                        'total_price' => (float)$unitpro['金额'],
                        'appraise_price' => (float)$unitpro['其中暂估价'],
                        'major' => $major,
                        'project_place' => $project_place,
                        'level' => 2,
                        'pid' => $firstId,
                        'path' => $firstId,
                        'createtime' => time(),
                        'updatetime' => time(),
                    ];
                    $twoId = Db::name('project_items')->insertGetId($row);
                    if (!$twoId) {
                        throw new Exception(__('导入失败，请检查数据格式'));
                    }
                    if (empty($unitpro->分部分项工程量清单->清单子目)) {
                        continue;
                    }
                    //分部分项工程量清单
                    foreach ($unitpro->分部分项工程量清单->清单子目 as $subItem) {
                        $row = [
                            'caijiakuid' => CAIJIAKU_ID,
                            'admin_id' => $this->auth->id,
                            'project_id' => $project_id,
                            'name' => (string)$subItem->项目名称,
                            'code' => (string)$subItem->项目编码,
                            'description' => (string)$subItem->项目特征,
                            'quantity' => (float)$subItem->工程数量,
                            'unit' => (string)$subItem->计量单位,
                            'unit_price' => (float)$subItem->综合单价,
                            'total_price' => (float)$subItem->综合合价,
                            'labor_cost' => (float)$subItem->综合单价['人工费单价'],
                            'material_cost' => (float)$subItem->综合单价['材料费单价'],
                            'machinery_cost' => (float)$subItem->综合单价['机械使用费单价'],
                            'management_cost' => (float)$subItem->综合单价['管理费单价'],
                            'profit' => (float)$subItem->综合单价['利润单价'],
                            'calculation_rules' => (string)$subItem->计算规则,
                            'appraise_price' => 0,
                            'level' => 3,
                            'pid' => $twoId,
                            'path' => $firstId.','.$twoId,
                            'createtime' => time(),
                            'updatetime' => time(),
                        ];
                        $threeId = Db::name('project_items')->insertGetId($row);
                        if (!$threeId) {
                            throw new Exception(__('导入失败，请检查数据格式'));
                        }
                        if (empty($subItem->清单明细->定额子目)) {
                            continue;
                        }
                        $subchildData = [];
                        foreach ($subItem->清单明细->定额子目 as $subchildItem) {
                            $major_txt = (string)$subchildItem->专业;
                            $major = array_flip($this->projectConfig['project_major'])[$major_txt] ?? 0;
                            $subchildData[] = [
                                'caijiakuid' => CAIJIAKU_ID,
                                'admin_id' => $this->auth->id,
                                'project_id' => $project_id,
                                'name' => (string)$subchildItem->名称,
                                'code' => (string)$subchildItem->编码,
                                'description' => (string)$subchildItem->项目特征,
                                'quantity' => (float)$subchildItem->数量,
                                'unit' => (string)$subchildItem->单位,
                                'unit_price' => (float)$subchildItem->综合单价,
                                'total_price' => (float)$subchildItem->综合合价,
                                'labor_cost' => (float)$subchildItem->综合单价['人工费单价'],
                                'material_cost' => (float)$subchildItem->综合单价['材料费单价'],
                                'machinery_cost' => (float)$subchildItem->综合单价['机械使用费单价'],
                                'management_cost' => (float)$subchildItem->综合单价['管理费单价'],
                                'profit' => (float)$subchildItem->综合单价['利润单价'],
                                'pricing_base' => (float)$subchildItem->计价基数,
                                'major' => $major,
                                'appraise_price' => 0,
                                'level' => 4,
                                'pid' => $threeId,
                                'path' => $firstId.','.$twoId.','.$threeId,
                                'createtime' => time(),
                                'updatetime' => time(),
                            ];
                            //人材机
                            if (empty($subchildItem->定额明细)) {
                                continue;
                            }
                            $recaiji = [];
                            foreach ($subchildItem->定额明细->工料机子目 as $recaijiItem) {
                                $code = (string)$recaijiItem['编码'];
                                $catename_key = (int)$recaijiItem['类别'];
                                $catename = $this->projectConfig['materials_types'][$catename_key] ?? '';
                                if (in_array($code, $rencaiji_codes)) continue;
                                $recaiji[] = [
                                    'caijiakuid' => CAIJIAKU_ID,
                                    'admin_id' => $this->auth->id,
                                    'project_id' => $project_id,
                                    'name' => (string)$recaijiItem['名称'],
                                    'code' => $code,
                                    'description' => (string)$recaijiItem['规格型号'],
                                    'unit' => (string)$recaijiItem['单位'],
                                    'quantity' => (float)$recaijiItem['数量'],
                                    'tax_unit_price' => (float)$recaijiItem['市场价'],
                                    'tax_total_price' => (float)$recaijiItem['合价'],
                                    'catename' => $catename,
                                    'createtime' => time(),
                                    'updatetime' => time(),
                                ];
                                $rencaiji_codes[] = $code;
                            }
                            if (!empty($recaiji)) {
                                $rs = Db::name('project_rencaiji')->insertAll($recaiji);
                                if (!$rs) {
                                    throw new Exception(__('导入失败，请检查数据格式'));
                                }
                            }

                        }
                        if (!empty($subchildData)) {
                           $rs = Db::name('project_items')->insertAll($subchildData);
                           if (!$rs) {
                                throw new Exception(__('导入失败，请检查数据格式'));
                            }
                        }
                    }
                    if (empty($unitpro->措施项目清单->措施子目)) {
                        continue;
                    }
                    //措施项目清单
                    foreach ($unitpro->措施项目清单->措施子目 as $subItem) {
                        $class = (string) $subItem->项目类型;
                        if ($class == '总价') {
                            continue;
                        }
                        $row = [
                            'caijiakuid' => CAIJIAKU_ID,
                            'admin_id' => $this->auth->id,
                            'project_id' => $project_id,
                            'name' => (string)$subItem->项目名称,
                            'code' => (string)$subItem->项目编码,
                            'description' => (string)$subItem->项目特征描述,
                            'quantity' => (float)$subItem->工程数量,
                            'unit' => (string)$subItem->计量单位,
                            'unit_price' => (float)$subItem->综合单价,
                            'total_price' => (float)$subItem->综合合价,
                            'labor_cost' => (float)$subItem->综合单价['人工费单价'],
                            'material_cost' => (float)$subItem->综合单价['材料费单价'],
                            'machinery_cost' => (float)$subItem->综合单价['机械使用费单价'],
                            'management_cost' => (float)$subItem->综合单价['管理费单价'],
                            'profit' => (float)$subItem->综合单价['利润单价'],
                            'calculation_rules' => (string)$subItem->计算规则,
                            'appraise_price' => 0,
                            'level' => 3,
                            'pid' => $twoId,
                            'path' => $firstId.','.$twoId,
                            'createtime' => time(),
                            'updatetime' => time(),
                        ];
                        $threeId = Db::name('project_items')->insertGetId($row);
                        if (!$threeId) {
                            throw new Exception(__('导入失败，请检查数据格式'));
                        }
                        if (empty($subItem->措施明细->定额子目)) {
                            continue;
                        }
                        $subchildData = [];
                        foreach ($subItem->措施明细->定额子目 as $subchildItem) {
                            $major_txt = (string)$subchildItem->专业;
                            $major = array_flip($this->projectConfig['project_major'])[$major_txt] ?? 0;
                            $subchildData[] = [
                                'caijiakuid' => CAIJIAKU_ID,
                                'admin_id' => $this->auth->id,
                                'project_id' => $project_id,
                                'name' => (string)$subchildItem->名称 ?? '',
                                'code' => (string)$subchildItem->编码 ?? '',
                                'description' => '',
                                'quantity' => (float)$subchildItem->数量,
                                'unit' => (string)$subchildItem->单位,
                                'unit_price' => (float)$subchildItem->综合单价,
                                'total_price' => (float)$subchildItem->综合合价,
                                'labor_cost' => (float)$subchildItem->综合单价['人工费单价'],
                                'material_cost' => (float)$subchildItem->综合单价['材料费单价'],
                                'machinery_cost' => (float)$subchildItem->综合单价['机械使用费单价'],
                                'management_cost' => (float)$subchildItem->综合单价['管理费单价'],
                                'profit' => (float)$subchildItem->综合单价['利润单价'],
                                'pricing_base' => (float)$subchildItem->计价基数,
                                'major' => $major,
                                'appraise_price' => 0,
                                'level' => 4,
                                'pid' => $threeId,
                                'path' => $firstId.','.$twoId.','.$threeId,
                                'createtime' => time(),
                                'updatetime' => time(),
                            ];
                            //人材机
                            if (empty($subchildItem->定额明细)) {
                                continue;
                            }
                            $recaiji = [];
                            foreach ($subchildItem->定额明细->工料机子目 as $recaijiItem) {
                                $code = (string)$recaijiItem['编码'];
                                if (in_array($code, $rencaiji_codes)) continue;
                                $catename_key = (int)$recaijiItem['类别'];
                                $catename = $this->projectConfig['materials_types'][$catename_key] ?? '';
                                $recaiji[] = [
                                    'caijiakuid' => CAIJIAKU_ID,
                                    'admin_id' => $this->auth->id,
                                    'project_id' => $project_id,
                                    'name' => (string)$recaijiItem['名称'],
                                    'code' => (string)$recaijiItem['编码'],
                                    'description' => (string)$recaijiItem['规格型号'],
                                    'unit' => (string)$recaijiItem['单位'],
                                    'quantity' => (float)$recaijiItem['数量'],
                                    'tax_unit_price' => (float)$recaijiItem['市场价'],
                                    'tax_total_price' => (float)$recaijiItem['合价'],
                                    'catename' => $catename,
                                    'createtime' => time(),
                                    'updatetime' => time(),
                                ];
                                $rencaiji_codes[] = $code;
                            }
                            if (!empty($recaiji)) {
                                $rs = Db::name('project_rencaiji')->insertAll($recaiji);
                                if (!$rs) {
                                    throw new Exception(__('导入失败，请检查数据格式'));
                                }
                            }
                        }
                        if (!empty($subchildData)) {
                            $rs = Db::name('project_items')->insertAll($subchildData);
                            if (!$rs) {
                                throw new Exception(__('导入失败，请检查数据格式'));
                            }
                        }
                    }
                }
            }
            $project_assess = [];
            if (!empty($xml->总工程->材料总汇->评审材料)) {
                foreach ($xml->总工程->材料总汇->评审材料->评审材料子目 as $value) {
                    $catename_key = (int)$value['类别'];
                    $catename = $this->projectConfig['materials_types'][$catename_key] ?? '';
                    $project_assess[] = [
                        'caijiakuid' => CAIJIAKU_ID,
                        'admin_id' => $this->auth->id,
                        'project_id' => $project_id,
                        'name' => (string)$value['名称'],
                        'code' => (string)$value['编码'],
                        'description' => (string)$value['规格型号'],
                        'unit' => (string)$value['单位'],
                        'quantity' => (float)$value['数量'],
                        'unit_price' => (float)$value['市场单价'],
                        'total_price' => (float)$value['合价'],
                        'reference_price' => (float)$value['评审参考价'],
                        'tax' => (float)$value['进项税率'],
                        'catename' => $catename,
                        'createtime' => time(),
                        'updatetime' => time(),
                    ];
                }
            }
            if (!empty($project_assess)) {
                $chunkSize = 200; // 每次插入的数据条数
                $dataChunks = array_chunk($project_assess, $chunkSize); // 将数据分割成小数组
                foreach ($dataChunks as $chunk) {
                    $res = Db::name('project_assess')->insertAll($chunk); // 分批插入数据
                }
            }
            Db::commit();
        } catch (\Exception $e) {
            Db::rollback();
            $this->error($e->getMessage());
        }
        $this->success(($currentIndex == count($filesArr) - 1 ? '导入完成' : ($currentIndex+1).'/'.count($filesArr).'正在导入中...'));
    }

     /**
     * 删除
     *
     * @param $ids
     * @return void
     * @throws DbException
     * @throws DataNotFoundException
     * @throws ModelNotFoundException
     */
    public function del($ids = null)
    {
        if (false === $this->request->isPost()) {
            $this->error(__("Invalid parameters"));
        }
        $ids = $ids ?: $this->request->post("ids");
        if (empty($ids)) {
            $this->error(__('Parameter %s can not be empty', 'ids'));
        }
        $pk = $this->model->getPk();
        $adminIds = $this->getDataLimitAdminIds();
        if (is_array($adminIds)) {
            $this->model->where($this->dataLimitField, 'in', $adminIds);
        }
        $list = $this->model->where($pk, 'in', $ids)->select();

        $count = 0;
        Db::startTrans();
        try {
            foreach ($list as $item) {
                $project_id = $item['id'];
                $count += $item->delete();
                ProjectItems::where('project_id', $project_id)->update(['deletetime' => time()]);
                ProjectRencaiji::where('project_id', $project_id)->update(['deletetime' => time()]);
                ProjectAssess::where('project_id', $project_id)->update(['deletetime' => time()]);
                
            }
            Db::commit();
        } catch (PDOException|Exception $e) {
            Db::rollback();
            $this->error($e->getMessage().'--'.json_encode($e->getData(), 256));
        }
        if ($count) {
            $this->success();
        }
        $this->error(__('No rows were deleted'));
    }

    /**
     * 真实删除
     *
     * @param $ids
     * @return void
     */
    public function destroy($ids = null)
    {
        if (false === $this->request->isPost()) {
            $this->error(__("Invalid parameters"));
        }
        $ids = $ids ?: $this->request->post('ids');
        $pk = $this->model->getPk();
        $adminIds = $this->getDataLimitAdminIds();
        if (is_array($adminIds)) {
            $this->model->where($this->dataLimitField, 'in', $adminIds);
        }
        if ($ids) {
            $this->model->where($pk, 'in', $ids);
        }
        $count = 0;
        Db::startTrans();
        try {
            $list = $this->model->onlyTrashed()->select();
            foreach ($list as $item) {
                $project_id = $item['id'];
                $count += $item->delete(true);
                Db::name('project_items')->where('project_id', $project_id)->delete();
                Db::name('project_rencaiji')->where('project_id', $project_id)->delete();
                Db::name('project_assess')->where('project_id', $project_id)->delete();
            }
            Db::commit();
        } catch (PDOException|Exception $e) {
            Db::rollback();
            $this->error($e->getMessage());
        }
        if ($count) {
            $this->success();
        }
        $this->error(__('No rows were deleted'));
    }

    /**
     * 还原
     *
     * @param $ids
     * @return void
     */
    public function restore($ids = null)
    {
        if (false === $this->request->isPost()) {
            $this->error(__('Invalid parameters'));
        }
        $ids = $ids ?: $this->request->post('ids');
        $pk = $this->model->getPk();
        $adminIds = $this->getDataLimitAdminIds();
        if (is_array($adminIds)) {
            $this->model->where($this->dataLimitField, 'in', $adminIds);
        }
        if ($ids) {
            $this->model->where($pk, 'in', $ids);
        }
        $count = 0;
        Db::startTrans();
        try {
            $list = $this->model->onlyTrashed()->select();
            foreach ($list as $item) {
                $project_id = $item['id'];
                $count += $item->restore();
                Db::name('project_items')->where('project_id', $project_id)->update(['deletetime' => null]);
                Db::name('project_rencaiji')->where('project_id', $project_id)->update(['deletetime' => null]);
                Db::name('project_assess')->where('project_id', $project_id)->update(['deletetime' => null]);
            }
            Db::commit();
        } catch (PDOException|Exception $e) {
            Db::rollback();
            $this->error($e->getMessage());
        }
        if ($count) {
            $this->success();
        }
        $this->error(__('No rows were updated'));
    }
}
